Gyazo と GKE
2022-05-17 (Tue) 19:55 スタート予定 (15m)
準備
Gyazo のメンテや開発をやってます
おもにバックエンド関連 (Rails, golang, etc...)やたまに DevOps 今日は DevOps のお話
Gyazo と GKE
deploy
branch staging
Gyazo と GKE
GCP とか Kubernetes (k8s) が何かはなんとなくわかっている前提で話をします
staging cluster では branch staging と呼ばれているものが動いている
他にもイントラ系 kibana, grafana などが動いている GKE cluster もある...
なぜ GKE (Kubernetes)?
Gyazo の初期のころは素朴にレンタルサーバー的なホスティングのマシン上で動いていた 直近では GCE の instance template から instance group 作成
docker for mac が登場して開発者のローカル環境は docker-compose に
rbenv や nvm が必要無いので楽
deploy 先も コンテナ化 or Full managed な PaaS に移行して楽をしたい
ruby 以外にもフロントエンドのビルドには node.js のツールが必要
コンテナにすると最終 image は node.js なしで済む
サーバーホスト管理したくない...
アップロードや画像配信のアプリケーションは分かれていてやや複雑
メインは Rails だけど画像バイナリを扱うところは golang
heroku みたいなシンプルな PasS では難しい
アプリケーションコードをほぼそのまま移行するにはその複雑さを再現できる Kubernetes がちょうどよかった
k8s cluster 内 network でお互いにアクセス
最近は Serverless VPC Access で Cloud Run とかから GCP のネットワークに接続とかできるらしいけど...
pod に複数のコンテナ (nginx, ruby server, fluentd, etc...)
一つのコンテナに突っ込むのは辛そう...
Gyazo の GKE cluster はどんな感じに運用されているのか
production 環境への入り口を制限したい
GCP 外部の CI から deploy するためには service account key などが必要になる
各CIに self-hosted runner とかあるけど...
Cloudbuild の step としては
普通に docker image をビルドして
kubectl apply で service, deployment などのリソースを更新
deploy で工夫してるところだと...
code:manifest.yaml
kind: Deployment
spec:
template:
metadata:
annotations:
kubernetes.io/change-cause: "${date} TAG=${IMAGE_TAG}"
https://nota.gyazo.com/14a4f6252f1ec8ce3ace4959c32183fa
slack で rollback 方法を通知
https://nota.gyazo.com/3abf1be4b1b039d1c599cb9526752caf
構成変更するのに yaml のパッチみたいなの書くのですが冗長だし自由度が低い...
単純なところは bash の heredoc 使ったほうが簡単
シンプルな yaml, json 汎用管理ツールみたいなのに切り替えたい...
branch staging はどういうしくみなのか?
URL ルーティング
scale to zero
branch staging へのリクエスト
https://gyazo.com/64bf0311e7c18adaa7f04f0c6f064782
Google HTTP Load balancer の backend service として staging-proxy という nginx コンテナの service を指定 nginx.conf で --g で終わるサブドメインは upstream .default.svc.cluster.local に流れるように...
e.g. my-branch--g.gyazo.example -> my-branch--g.default.svc.cluster.local
そうすると cluster network の service my-branch--g にリクエストが流れる...
branch staging の scale to zero
HPA は pod を 0 にできない
どんどんブランチができると GKE cluster の CPU/memory resources を圧迫
手動で kubectl delete deployment my-branch--g とかキビシイ
HPA は 0 から復活することもできない
ブランチの数が増えたときに挙動のデバッグが大変であきらめた
今見たら僕の helm3 対応 commit が最後で archive になってる...
https://nota.gyazo.com/dc8f031e1a0e88944d75b64ef5ec79c1
すごいwakix.icon
knative serving (Cloud Run はこれで動いている) でも scale to zero できるみたいだけど...
1 container/ 1 pod という制限があったり (このへん変わるみたいだけど...)
やりたいことは環境によって微妙に違うはず...
k8s API 自体は REST なので難しくない
試しに ruby で実装してみるか... -> branch-manager.rb
branch-manager.rb がやってること
https://gyazo.com/6d3a387787460f34b20d31ba0c705a8a
上記 staging-proxy の nginx.conf で --g の svc に upstream するときに branch-manager にもリクエストを mirror
該当する service の deployment の pod が 0 だったら kubectl scale deployment/my-branch--g --replicas=1 相当の API を叩く
各 service の最終アクセス日時を記録しておいて、一定時間アクセスが無い service は scale --replicas=0
基本はコレだけ
branch-manager.rb の実装
100行ぐらいの ruby script
code:Gemfile
gem "sinatra"
gem 'rest-client'
gem 'rufus-scheduler'
gem 'tzinfo-data' # Internally required by rufus-scheduler
gem 'dalli'
rbac で適切な権限を与えていれば以下のようなリクエストヘッダ設定で API アクセスできる code:ruby
def resource_client
headers: {
'Content-Type' => 'application/strategic-merge-patch+json'
}
)
else
token = File.read('/var/run/secrets/kubernetes.io/serviceaccount/token')
ssl_ca_file: '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt',
headers: {
'Content-Type' => 'application/strategic-merge-patch+json'
}
)
end
end
たとえばこんな感じ
code:ruby
json = JSON.parse(res.body)
API を調べるには kubectl -v8
https://nota.gyazo.com/193dc56018618932869722ff243da7ff
ローカルでデバッグするときは
code:sh
kubectl --cluster=gyazo-staging proxy
code:out
Starting to serve on 127.0.0.1:8001
おわり
こんな感じに Nota では DevOps 系のタスクもひっそりとやってます
インフラ/セキュリティエンジニア募集してます
最初は helpfeel の DevOps を助けて欲しいけど、長期的にはサービス共通基盤みたいなのができるとかっこいいと思ってる